#include <iostream>
using namespace std;

class MyClass
{
public:
    int x;
    int *p;

public:
    // 1. 默认构造函数
    MyClass() // 默认无参的构造函数 : 用来创建对象的时候，给对象的成员变量赋一个初始值。要是你没有做显示初始化，那成员的值可能是不确定的，比如数字会是随机值，指针可能会是 nullptr。
    {
    }
    MyClass(int val)
    {
        p = new int(val);
    }
    // 2. 默认析构函数
    // 当对象被销毁时，析构函数会自动被调用，释放对象占用的资源
    ~MyClass() {} // 默认析构函数，啥也不做
    /*
        默认析构函数什么都不做，它会帮你销毁对象，但不会释放 new 分配的内存。
        有动态资源时（比如 new 分配的内存），一定要自己写析构函数，用 delete 手动释放内存，防止内存泄漏。
        没有动态资源时，默认的析构函数就够用了。
    */

    // 3. 默认拷贝构造函数: 给你生成一个默认的拷贝构造函数。它会把原对象的成员变量逐个复制过来   浅拷贝
    MyClass(const MyClass &other) : x(other.x) {}
    /*
    浅拷贝存在的问题：我里面有一个p指针，我将obj1通过默认拷贝构造，赋值非obj2，那么obj1的p值赋值给了obj2的p，那么这2个p就指向同一个内存空间，那么析构的时候，会造成双重释放，造成程序崩溃
    */
    // 3. 深拷贝:
    /*
    MyClass(const MyClass &other)
    {
        p = new int(*(other.p)); // 重新开辟一块空间给这个p
    }
    */

    // 4. 默认重载赋值运算符:  把一个对象赋值给另一个对象时,C++ 会自动调用赋值运算符函数,会对每个成员变量进行拷贝，就像拷贝构造函数一样。
    // 这也是浅拷贝，也会出现动态内存的问题
    MyClass &operator=(const MyClass &other)
    {
        x = other.x;
        p = other.p;
        return *this;
    }
    // 深拷贝
    MyClass &operator=(const MyClass &other)
    {
        x = other.x; // 这个没有什么问题
        p = new int(*(other.p));
        return *this;
    }
    /*
        默认赋值运算符只是做浅拷贝，它会简单地复制成员变量的值。
        如果有指针成员，默认的浅拷贝可能导致多个对象指向同一块内存，容易出问题。
        自定义赋值运算符来做深拷贝，确保每个对象都有独立的内存空间，避免出现资源共享问题。  
    */

    // 5. 默认重载取地址运算符:
    MyClass *operator&()
    {
        return this; // 这里返回的是对象本身的地址
    }
    // 默认重载取址运算符（const）: 返回常量地址
    // 常量对象的值不能被修改，那如果你需要获取常量对象的地址怎么办？这时，C++ 为你准备了一个const 版本的取址运算符
    const MyClass *operator&() const
    {
        return this;
    }

    // 6. 默认移动构造函数(C++11)： 将资源从一个对象转移到另一个对象，而不需要复制数据
    // 接收一个右值引用对象（临时对象、或者std::move（）返回的）
    // 为什么要移动构造？？？
    //     效率提升：移动比复制快，特别是当对象很大时。
    //     避免浪费资源：移动语义避免了不必要的内存分配和释放。
    MyClass(MyClass &&other) // 当你有一个临时对象 （比如一个将要被销毁的对象）时，移动构造函数就会被调用
    {
        p = other.p;
        other.p = nullptr;
    }

    // 7. 默认重载移动赋值运算符（C++11）:   我来接管你的资源，别浪费了
    // 将一个临时对象赋值给另一个对象时，帮助你高效地转移资源，避免浪费时间和内存进行复制操作
    MyClass &operator=(MyClass &&other)
    {
        if (this != &other)
        {
            delete p; // 先释放当前对象的资源
            p = other.p;
            other.p = nullptr;
        }
        return *this;
    }
};

int main()
{

    MyClass obj;
    cout << obj.x << endl; // 随机值 ，因为没有显示初始化

    return 0;
}